package main

import (
	"fmt"
	"os"
)

// 定义emp
type Emp struct {
	Id int
	Name string
	Next *Emp
}

// 定义EmpLink，不代表头，即第一个节点就存放雇员
type EmpLink struct {
	Head *Emp
} 

// 添加员工的方法，保证添加时，编号从小到大
func (this *EmpLink) Insert(emp *Emp) {
	cur := this.Head // 这是辅助指针
	var pre *Emp = nil // 这是辅助指针,pre在cur前面
	// 如果当前的EmpLink本身是空链表
	if cur == nil {
		this.Head = emp
		return
	}
	// 如果不是空链表，给emp找到对应的位置并插入
	// 思路是让cur和emp比较，然后pre保持在cur前面
	for {
		if cur != nil {
			// 比较
			if cur.Id > emp.id {
				// 找到位置了
				break
			}
			pre = cur // 保证同步
			cur = cur.Next
		} else {
			break
		}
	}

	// 退出时，我们看下是否将emp添加到链表最后
	if cur == nil {
		pre.Next = emp
		emp.Next = cur
	} else {
		pre.Next = emp
		emp.Next = cur
	}
}

// 定义HashTable，含有一个链表数组
type HashTable struct {
	LinkArr [7]EmpLink
}

// 给哈希表编写Insert方法，添加雇员
func (this *HashTable) Insert(emp *Emp) {
	// 使用散列函数确定将该雇员添加到哪个链表
	LinkArr [7]EmpLink
}

// 编写方法，显示哈希表所有的雇员
func (this *HashTable) ShowAll() {
	for i := 0; i < len(this.LinkArr); i++ {
		this.LinkArr[i].ShowLink(i)
	}
}

// 显示链表信息
func (this *EmpLink) ShowLink(no int) {
	if this.Head == nil {
		fmt.Printf("链表%d 没有数据\n", no)
		return
	}

	// 遍历当前列表并显示数据
	cur := this.Head // 辅助指针
	for {
		if cur != nil {
			fmt.Printf("链表%d, 雇员id=%d， 名字=%s", no, cur.Id, cur.Name)
			cur = cur.Next
		} else {
			break
		}
	}
	fmt.Println()
}

// 编写散列函数
func (this *HashTable) HashFun(id int) int {
	return id % 7 // 得到一个值，就是对应链表的下标
	linkNo := this.HashFun(emp.Id)
	// 使用对应的链表添加
	this.LinkArr[linkNo].Insert(emp)
}

// 查找的方法
func (this *HashTable) FindById(id int) *Emp {
	linkNo := this.HashFun(emp.Id)
	return this.LinkArr[linkNo].FindById(id)
}

// 根据id查找对应的雇员,如果没有就返回nil
func (this *EmpLink) FindById(id int) *Emp {
	cur := this.Head
	for {
		if cur != nil && cur.Id == id {
			return cur
		} else if cur == nil {
			break
		}
		cur = cur.Next
	}
	return nil
}

func (this *Emp) ShowMe() {
	fmt.Printf("链表%d 找到该雇员 %d\n", this.Id % 7, this.Id)
}

func main() {

	key := ""
	id := 0
	name := ""
	var hashtable HashTable
	for {
		fmt.Println("==========雇员系统菜单===========")
		fmt.Println("input 表示添加雇员")
		fmt.Println("show 表示显示雇员")
		fmt.Println("find 表示查找雇员")
		fmt.Println("exit 表示退出")
		fmt.Println("请输入你的选择：")
		fmt.Scanln(&key)
		switch key {
		case "input":
			fmt.Println("输入雇员id：")
			fmt.Scanln(&id)
			fmt.Println("输入雇员名字：")
			fmt.Scanln(&name)
			emp := &Emp {
				Id: id,
				Name: name,
			}
			hashtable.Insert(emp)
		case "show":
			hashtable.ShowAll()
		case "find":
			fmt.Println("请输入id：")
			fmt.Scanln(&id)
			emp := hashtable.FindById(id)
			if emp == nil {
				fmt.Printf("id=%d 的雇员不存在\n", id)
			} else {
				emp.ShowMe()
			}
		case "exit":
			os.Exit(0)
		default:
			fmt.Println("输入错误")
		}
	}

}